﻿/**
 * 
 */
package work;

import java.io.File;
import java.sql.Connection;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.h819.core.db.deprecated.MySQL;
import com.h819.core.db.deprecated.Oracle_std;
import com.h819.core.file.excel.jxl.ExcelUtils;
import com.h819.work.utils.StandardClassUtils;
import com.h819.work.utils.StandardUtils;
import com.h819.work.utils.WorksUtils;

/**
 * @author jianghui
 * 
 * \n 换行; \r 光标移至行首; \t 跳格（一个 Tab 键）
 * 
 * 
 */

public class BuyStdExcel {

	/**
	 * 读取Excel文件的内容
	 * 
	 * @param file
	 *            待读取的文件
	 * @return
	 */
	Logger log = Logger.getLogger(BuyStdExcel.class);
	ExcelUtils eu = new ExcelUtils();
	WorksUtils uw = new WorksUtils();
	ArrayList<String> classCode = StandardClassUtils.getClassCode_GN();

	//	登记为已到货.仅操作 mysql，只修改 goumai 根据已到货的情况，标记到货情况 根据标准号，更新 ydh = 1 ,并记录 dhrqtime 
	//	goumai 表中，dhrqtime 为空的记录，是以前提出但没有到货的记录
	//	到货登记的要求： 在出库单上面直接标记，这样能保证标准号规范，并且能发现不是提出购买而出版社那错的标准
	//  记录格式要求：到货标准号在 第一个 sheet ，第一列

	public void updateYdh(File file) {

		MySQL my = new MySQL();
		Connection mysqlConn = null;
		mysqlConn = my.getConnection(mysqlConn);

		Statement mysqlSelectStmt = null;
		Statement mysqlStmtUpdate = null;
		ResultSet mysqlSelectRs = null;

		String stdcode = "";

		// 已到货计数
		int countYdh = 0;
		// 未登记计数
		int countWdj = 0;

		//建立在全局，会话可以重复利用
		try {
			mysqlSelectStmt = mysqlConn.createStatement();
			mysqlStmtUpdate = mysqlConn.createStatement();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		Map<Integer, String> tm = eu.readExcel(file, 1, 1);

		Set<Integer> s = tm.keySet();
		Iterator<Integer> it_s = s.iterator();

		while (it_s.hasNext()) {//循环行
			// 元素为 TreeMap
			Integer lineNumber = it_s.next();
			String line = (String) tm.get(lineNumber);
			stdcode = StandardUtils.getStandardCode(line,classCode);

			if (stdcode == null) {// 不规范的标准号					
				log.info(stdcode + " is not in goumai");
				continue;
			}

			String mysqlQuery = "SELECT sid FROM goumai where stdcode ='"
					+ stdcode + "' ";
			String mysqlSid = null;

			try {

				// 核对是否重复

				mysqlSelectRs = mysqlSelectStmt.executeQuery(mysqlQuery);

				while (mysqlSelectRs.next()) {
					mysqlSid = mysqlSelectRs.getString("stdcode");

					log.info("stdcode in excle= " + stdcode
							+ ",   stdcode in mysql=" + mysqlSid);

					// mysql 中有，则说明该条目在 mysql 中登记过 更新 ydh=1,dhrqtime
					if (mysqlSid != null) {
						countYdh++;

						String mysqlupdate = "update std set ydh=1,dhrqtime=sysdate() where sid='"
								+ stdcode + "'";
						// log.info(mysqlupdate);
						mysqlStmtUpdate.execute(mysqlupdate);

					}

					// 否则，则在mysql中登记.
					else {
						countWdj++;
						log.info(stdcode + " 未在 mysql 中登记");
					}
				}// end while

			} catch (SQLException ex) {
				ex.printStackTrace();
				log.info("exception in updateYdh action.");

				my.closeDB(mysqlSelectRs, mysqlSelectStmt);
				my.closeDB(mysqlStmtUpdate);
				my.closeDB(mysqlConn);
			}
		}

		// 数据库操作已经完成，关闭连接，关闭函数本身已经有 try catch finally了，故不用在 finally 中在写了.
		my.closeDB(mysqlSelectRs, mysqlSelectStmt);
		my.closeDB(mysqlStmtUpdate);
		my.closeDB(mysqlConn);

		log.info("=============  mysql 中登记已到货的条目数： " + countYdh);
		log.info("=============  mysql 中不存在的条目数： " + countWdj);
	}

	// 新标准购买单流程
	// 出库：所有新收集的题录入平台 -> 按照指定年份提取到mysql(work->newstdtemp) -> 扣除
	// 90000、已到货、已有馆藏、3900
	// -> 正式购买单
	// 入库：用 updateYdh 函数，更新 goumai 表
	//
	// 用来提取平台库中指定年份之后的记录，存储到mysql goumai 表中
	// 提取条件：
	// 1. 指定年份之后(不必考虑发布日期和实施日期，公告发布之后，就应该出版发行)
	// 2. 国标或者行标
	// 3. 无电子文本
	/*
	 * @param year 指定年份
	 * 
	 */
	private void getStdByYearToMysql(String year) {
		

		MySQL my = new MySQL();
		Oracle_std oracle = new Oracle_std();
		Connection mysqlConn = null;
		Connection oracleConn = null;
		mysqlConn = my.getConnection(mysqlConn);
		oracleConn = oracle.getConnection(oracleConn);

		Statement mysqlStmt = null;
		Statement oracleStmt = null;

		ResultSet oracleRs = null;
		
		int count=0;
		
		//不需要购买单标准类别,这部分标准单独从专业的出版社购买.
		//其他的都从标准出版社购买
		String classno [] ={"QC","QS","JB","NY","SC"};
		
		boolean isClass = false;
		boolean isRangeYear = false;
		


		// 国标、行表中所有无文本的记录，提取出来之后，根据标准号拆分年代，不用发布日期，因为发布日期不准
		String queryOrcle = "select t.standard_code,t.namecn,t.issue_time,t.act_time from st_standard t where t.class_two_code='GB' or t.class_two_code='HB' and t.text_address is null";
		String mysqlTruncate = "truncate table newstdtemp";

		log.info("begin get Stdcode from oracle to mysql...");

		log.info("queryOrcle :"+queryOrcle);
		
		try {

			mysqlStmt = mysqlConn.createStatement();
			
			// 每次清空 mysql 临时表.此类操作，一定要小心，不要误操作正式数据
			mysqlStmt.executeUpdate(mysqlTruncate);

			oracleStmt = oracleConn.createStatement();

			if (oracleStmt.execute(queryOrcle)) {
				oracleRs = oracleStmt.getResultSet();

				while (oracleRs.next()) {
					String stdcode = (String) oracleRs
							.getString("standard_code");
					String namecn = (String) oracleRs.getString("namecn");

					Date time1 = oracleRs.getDate("issue_time");
					Date time2 = oracleRs.getDate("act_time");
					String issue_time = null;
					String act_time = null;

					// 如果字段中没有值，那么会为 null,所以 toString() 的时候会发生异常，此时要判断一下
					if (time1 != null) {
						issue_time = time1.toString();
					}

					if (time2 != null) {
						act_time = time2.toString();
					}
					

					
					System.out.println("stdcode :" + stdcode);
					System.out.println("namecn :" + namecn);
					System.out.println("issue_time :" + issue_time);
					System.out.println("act_time :" + act_time);
					
					
					for(String c:classno) {
						//log.info("c :"+c);
						if(stdcode.startsWith(c)){
							isClass=true;
							break;
						}		
					}
						
					isRangeYear=uw.isStandardCodebyYear(stdcode, year);
					//isClass==false && 
					// 满足要求，存入 mysql
					if (isRangeYear==true) {

						count++;
						
						String mysqlInsert = "insert into newstdtemp (stdcode,stdname,issue_time,act_time,date) values ('"
								+ stdcode
								+ "','"
								+ namecn
								+ "','"
								+ issue_time
								+ "','" + act_time + "',sysdate())";
						//log.info(mysqlInsert);

						mysqlStmt.executeUpdate(mysqlInsert);// 存入到 mysql

					}

				}
			}
			log.info("end get Stdcode from oracle to mysql...");
			log.info("总计从平台中提取时间大于等于 "+year+" 的数量是："+count);
			oracle.closeDB(oracleRs, oracleStmt, oracleConn);
			my.closeDB(mysqlStmt, mysqlConn);

		} catch (SQLException ex) {
			log.info("exception in query action.");
			oracle.closeDB(oracleRs, oracleStmt, oracleConn);
			my.closeDB(mysqlStmt, mysqlConn);
		}
	}
	
	
	
	//按照指定年份,统计平台中的题录情况
	private void countStandardCodeByYear(String year) {
		
		Oracle_std oracle = new Oracle_std();
		Connection oracleConn = null;
		oracleConn = oracle.getConnection(oracleConn);

		Statement oracleStmt = null;
		ResultSet oracleRs = null;
		
		int countBefore=0;
		int countAfter=0;

		boolean isRangeYear = false;

		// 国标、行表中所有无文本的记录，提取出来之后，根据标准号拆分年代，不用发布日期，因为发布日期不准
		String queryOrcle = "select t.standard_code,t.namecn,t.issue_time,t.act_time from st_standard t " +
				"where t.class_two_code='DB' and t.text_address is not null";
		//and t.text_address is not null

		log.info("queryOrcle :"+queryOrcle);
		
		try {

			oracleStmt = oracleConn.createStatement();

			if (oracleStmt.execute(queryOrcle)) {
				oracleRs = oracleStmt.getResultSet();

				while (oracleRs.next()) {
					String stdcode = (String) oracleRs
							.getString("standard_code");
					String namecn = (String) oracleRs.getString("namecn");

					Date time1 = oracleRs.getDate("issue_time");
					Date time2 = oracleRs.getDate("act_time");
					String issue_time = null;
					String act_time = null;

					// 如果字段中没有值，那么会为 null,所以 toString() 的时候会发生异常，此时要判断一下
					if (time1 != null) {
						issue_time = time1.toString();
					}

					if (time2 != null) {
						act_time = time2.toString();
					}

					System.out.println("stdcode :" + stdcode);
//					System.out.println("namecn :" + namecn);
//					System.out.println("issue_time :" + issue_time);
//					System.out.println("act_time :" + act_time);

					//year = 2008,大于等于 2008 年
					isRangeYear=uw.isStandardCodebyYear(stdcode, year);

					if(isRangeYear)
						countBefore++;
					else 
						countAfter++;
				}
			}
			
			log.info("总计从平台中提取时间大于等于 "+year+" 的数量是："+countBefore);
			log.info("总计从平台中提取时间大于等于 "+year+" 的数量是："+countAfter);
			oracle.closeDB(oracleRs, oracleStmt, oracleConn);


		} catch (SQLException ex) {
			log.info("exception in oracle query action.");
			oracle.closeDB(oracleRs, oracleStmt, oracleConn);

		}
	}
	

	// 生成指定年份的购买单
	// 注意生成购买单的条件：主要是依托平台中的数据，扣除已经买到的数据
	// 
	// *****   每次出新购买单独时候，上次的购买单作废
	//
	// 因为要购买所有的文本，所以没有考虑后来深圳购买的数据
	public void createBuyStd(File buyExcle, String year) {

		// 首先提取指定年限之后的数据
		getStdByYearToMysql(year);

		// 开始比较，并生成购买单
		MySQL my = new MySQL();
		Connection mysqlConn = null;
		mysqlConn = my.getConnection(mysqlConn);
		Statement mysqlShouldBuyStmt = null;
		Statement mysqlAlreadyInStmt = null;

		ResultSet mysqlShouldBuyRs = null;
		ResultSet mysqlAlreadyInRs = null;
		int countInsert = 0;
		int countAlready = 0;
		int countAll = 0;

		ArrayList<ArrayList<String>> alist2 = new ArrayList<ArrayList<String>>();

		// 查询应该购买的题录,生成购买 excel;
		// 还没有登记到 goumai 的数据，进行登记
		// goumai 表用来登记是否提出购买和标注是否到货,便于以后查询

		// 符合此条件的数据，都是应该生成购买单的数据,其中没有在 goumai 表登记的，要进行登记
		// goumai 表存在的意义是:记录哪些题录已经提出过购买。如果没有 goumai 表也可以出购买单，即生成购买单和 goumai 表
		// 没有关系.
		String mysqlShouldBuy = "select a.stdcode,a.stdname,a.issue_time,a.act_time,a.date  from newstdtemp a where "
				//不在 90000 购买单中	
				+ "not exists(select 1 from nine b where a.stdcode = b.stdcode) and "
				// 不在 库房已有的记录中	
				+ "not exists(select 1 from bookstore c where a.stdcode = c.stdcode) and "
				//不在 新标准 购买记录中，因为新购买的是另外一个单子，无论 goumai 中是否到货	
				// 注意此条件：
				// goumai 中无记录；
				+ "not exists(select 1 from goumai d where a.stdcode = d.stdcode and d.ydh=1) and "
				//不在 3900 购买记录中
				+ "not exists(select 1 from buybook e where a.stdcode = e.stdcode) "
				+ "ORDER BY a.stdcode ASC";

		try { 

			mysqlShouldBuyStmt = mysqlConn.createStatement();
			mysqlAlreadyInStmt = mysqlConn.createStatement();
			String stdcode = null;
			String namecn = null;

			String time3 = null;
			String issue_time = null;
			String act_time = null;

			mysqlShouldBuyRs = mysqlShouldBuyStmt.executeQuery(mysqlShouldBuy);

			while (mysqlShouldBuyRs.next()) {
				countAll++;			
				stdcode = (String) mysqlShouldBuyRs.getString("stdcode");
				namecn = (String) mysqlShouldBuyRs.getString("stdname");
				issue_time = (String) mysqlShouldBuyRs.getString("issue_time");
				act_time = (String) mysqlShouldBuyRs.getString("act_time");
				time3 = (String) mysqlShouldBuyRs.getString("date");

				// 如果字段中没有值，那么会为 null,所以 toString() 的时候会发生异常，此时要判断一下
				// 只有这两个值能出现 null，故只判断这两个即可
				// if (time1 != null) {
				// issue_time = time1.toString();
				// }
				//
				// if (time2 != null) {
				// act_time = time2.toString();
				// }

//				System.out.println("stdcode :" + stdcode);
//				System.out.println("namecn :" + namecn);
//				System.out.println("issue_time :" + issue_time);
//				System.out.println("act_time :" + act_time);
//				System.out.println("date :" + time3);

				// 生成购买单用
				ArrayList<String> alist = new ArrayList<String>();
				alist.add(stdcode);
				alist.add(namecn);
				alist.add(issue_time);
				alist.add(act_time);
				alist.add(time3.toString());
				alist2.add(alist);

				// 判断是否在goumai表中，如果已经登记跳过，如果没有登记，则 insert
				String mysqlAlreadyIn = "select stdcode from goumai where stdcode ='"
						+ stdcode + "'";
				//log.info("mysqlAlreadyIn:" + mysqlAlreadyIn);

				mysqlAlreadyInRs = mysqlAlreadyInStmt
						.executeQuery(mysqlAlreadyIn);

				// 更新 goumai 表
				if (mysqlAlreadyInRs.next()) {// 已经登记，跳过
					countAlready++;
					continue;
				}

				countInsert++;
				String mysqlInsert = "insert into goumai (stdcode,stdname,issue_time,act_time,picktime,createtime) values ('"
						+ stdcode
						+ "','"
						+ namecn
						+ "','"
						+ issue_time
						+ "','"
						+ act_time + "','" + time3.toString() + "',sysdate())";
				//log.info("mysqlInsert:" + mysqlInsert);
				mysqlAlreadyInStmt.executeUpdate(mysqlInsert);// 存入到 mysql
			}

			// 生成购买单
			ExcelUtils eu = new ExcelUtils();
			eu.writeListListValueToExcel(buyExcle, alist2);

			my.closeDB(mysqlShouldBuyRs, mysqlShouldBuyStmt);
			my.closeDB(mysqlAlreadyInRs, mysqlAlreadyInStmt);
			my.closeDB(mysqlConn);
			
			log.info("满足 <不在库房纸本中,不在3900购货单中,不在90000购买单中,goumai 表中未到货>的条件，应该提出购买的数目:" + countAll);
			log.info("goumai 表中已经登记的记录数是:" + countAlready);
			log.info("goumai 表中未登记，登记的记录数是:" + countInsert);

		} catch (SQLException ex) {
			log.info("exception in query action.");
			ex.printStackTrace();
			// oracle.closeDB(oracleRs, oracleStmt, oracleConn);
			my.closeDB(mysqlShouldBuyRs, mysqlShouldBuyStmt);
			my.closeDB(mysqlAlreadyInRs, mysqlAlreadyInStmt);
			my.closeDB(mysqlConn);
		}
	}

	public static void main(String[] args) {

		BuyStdExcel ex = new BuyStdExcel();

		// Ydh
		// ex.updateYdh(new File("D:/1.xls"));		
		//

	//	ex.createBuyStd(new File("D:/goumaidan.xls"), "2006");
		
		//ex.getStdByYearToMysql("2006");
		
		ex.countStandardCodeByYear("2008");

	}
}